home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
mxlist.zip
/
AMORT2.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-01-04
|
10KB
|
328 lines
Program AMORT2;
{$V-,N-,E- }
(*
This program uses the DMX unit to generate an amortization schedule.
It was recently updated for multiple mortgages and on-line help.
Two DMX objects are used in this unit:
The SelectWindow object uses a five-record editor to input
the financial parameters Year, Month, Amount, Rate, Years, and
Payment to calculate and compare five different loans schedules.
SELECTOR uses this object-type.
The AmortWindow object is a descendant of DMXviewer, so as to
scroll through the table without allowing changes. The DataAt
virtual function is modified to calculate each record as it
needs to be displayed. This may be slow on an 8088 CPU, but
the advantage to this method is that the entire table does not need
to be kept in memory.
AMORT uses this object-type.
The on-line help also makes use of DMX and object-oriented programming.
This is accomplished in the file DMX_LIST.PAS.
This program is meant only as a demonstration for various uses of
the DMX objects.
This program is designed for MONTHLY payments only. BI-WEEKLY mortgages
have a radically different schedule --although you may certainly modify
this program to accommodate week numbers instead of month names.
*)
uses Dos, Crt, DMX2, DMX_list;
type AmortRec = record
Year : word;
MonthName : string [12];
Principal : real;
Interest : real;
Balance : real;
end;
SelectRec = record
Year,Month : word;
Principal : real;
Interest : real;
Years : word;
Payment : real;
end;
SelectWindow = object (DMXwindow)
Info : array [0..4] of SelectRec;
procedure PickIt;
procedure ZeroizeRecord (var Data );
virtual;
procedure EvaluateField (RecNum : longint;
CellNum,Line : word);
virtual;
end;
AmortWindow = object (DMXviewer)
linedata : AmortRec;
Total : real;
Rate : real;
Payment : real;
Years : word;
Periods : word;
FirstMonth : word;
FirstYear : word;
LastPayment : word;
LastTotal : real;
procedure Amortize (prin,interest :real; ys,y,m :word);
function DataAt (recnum : longint) : pointer;
virtual;
end;
const maintitle = ' year month principal interest balance ';
baseformat = ' WWWW │ ____________ ║($R,RRR,RRR.RR)│($R,RRR,RRR.RR)║($RR,RRR,RRR.RR)';
spectitle = ' year month amount rate years payment ';
specformat = ' WWWW | WW ║ $rr,rrr,rrr.rr ║ %rr.rr | WW ║ $rrr,rrr.rr ';
cr = #13;
Esc = #27;
F1 = ';';
F9 = 'C';
Months : array [0..11] of string [12] =
('January ',
'February ',
'March ',
'April ',
'May ',
'June ',
'July ',
'August ',
'September',
'October ',
'November ',
'December ');
var Key,ext : char;
DOScolors : word; { original colors }
SELECTOR : SelectWindow; { selector object }
AMORT : AmortWindow; { viewer object }
{ ─────────────────────────────────────────────────────────────────────── }
function Radical (number,exponent : real) : real;
{ returns the value of number raised to the power of exponent }
begin
Radical := exp (Ln (abs (number)) * abs (exponent))
end;
{ ─────────────────────────────────────────────────────────────────────── }
function AmortPMT (prin,interest,term : real) : real;
{ amount of the periodic payment on the loan }
begin
AmortPMT := prin * (interest / (1 - (1 / (Radical (1 + interest,term)))));
end;
{ ─────────────────────────────────────────────────────────────────────── }
function AmortPRIN (pmt,interest,term : real) : real;
{ amount of the loan }
begin
AmortPRIN := (pmt * (1 - (1 / (Radical (1 + interest,term))))) / interest;
end;
{ ─────────────────────────────────────────────────────────────────────── }
function AmortWindow.DataAt (recnum : longint) : pointer;
{ The original descendant of this method returns a pointer }
{ to where the record would be stored in memory. }
{ This virtual method pretends to retrieve the next record }
{ by calculating the record contents in LINEDATA. }
{ The function then returns a pointer to LINEDATA. }
{ RECNUM is actually the payment number, minus zero. }
var i,j : word;
begin
With linedata do
begin
If LastPayment <> recnum then
begin
If LastPayment > recnum then
begin
LastPayment := 0;
LastTotal := Total;
end
else
Inc (LastPayment);
For i := LastPayment to recnum do
begin
Interest := Rate * LastTotal;
Principal := Payment - Interest;
LastTotal := LastTotal - Principal;
If recnum = pred (recordlimit) then
Balance := 0.0
else
Balance := LastTotal;
end;
LastPayment := recnum;
end;
Year := ((recnum + FirstMonth) div 12) + FirstYear;
MonthName := Months [(recnum + FirstMonth) mod 12];
end;
DataAt := addr (linedata);
end;
{ ─────────────────────────────────────────────────────────────────────── }
procedure AmortWindow.Amortize (prin,interest : real; ys,y,m : word);
{ This method initializes the amortization variables, and then runs EditData. }
var void : byte;
begin
FirstYear := y;
FirstMonth := m;
Total := prin;
Rate := interest / 100 / 12;
Years := ys;
Periods := Years * 12;
LastPayment := 32000;
Payment := AmortPMT (Total,Rate,Periods);
Window (6,2,75,24);
WindBorder (LightCyan);
TextAttr := bordercolor;
ClrScr;
GotoXY (2,23);
write ('F1 Help Your monthly payment is: $', Payment:1:2);
GotoXY (62,23);
write ('ESC Exit');
ClrPosition; { reset current record pointer }
OpenBuffer (void, sizeof (AmortRec) * Periods);
Repeat
EditData (void, Key,ext, [Esc],[F1]);
If ext = F1 then
ViewHelpWindow ('AMORT.HLP', 'B', 11,20,20,61, LightRed,$70);
Until (ext <> F1);
end;
{ ─────────────────────────────────────────────────────────────────────── }
procedure SelectWindow.ZeroizeRecord (var Data );
begin
{ Do nothing, and ignore the ^Y command. }
end;
{ ─────────────────────────────────────────────────────────────────────── }
procedure SelectWindow.EvaluateField (RecNum : longint; CellNum,Line : word);
begin
With Info [RecNum] do
begin
If Year = 0 then Year := 1990;
If (Month < 1) or (Month > 12) then Month := 1;
If Principal < 10 then Principal := 10.0;
If Interest <= 0 then Interest := 10.0;
If Years < 2 then Years := 2;
If (CellNum in [3..5]) or (Payment = 0.0) then
Payment := AmortPMT (Principal, (Interest / 100 / 12), Years * 12)
else
If CellNum = 6 then
Principal := AmortPRIN (Payment, (Interest / 100 / 12), Years * 12);
DisplayRecord (Info [RecNum], Line);
end;
end;
{ ─────────────────────────────────────────────────────────────────────── }
procedure SelectWindow.PickIt;
var i : word;
begin
showzeroes := True; { make any zero amounts visible }
For i := 0 to 4 do
begin
With Info [i] do
begin
Year := 1990;
Month := 1;
Principal := 10000.00;
Interest := 10;
Years := 30;
Payment := AmortPMT (Principal, (Interest / 100 / 12), Years * 12);
end;
end;
Repeat
Window (1,1,80,25);
TextAttr := Black;
ClrScr;
Window (10,7,71,15);
TextAttr := bordercolor;
WindBorder (Yellow);
ClrScr;
GotoXY (3,9);
write ('F1 Help F9 Amortize ESC Exit');
OpenBuffer (Info, sizeof (Info));
Repeat
EditData (Info, Key,ext, [Esc],[F1,F9]);
If ext = F1 then
ViewHelpWindow ('AMORT.HLP', 'A', 12,30,24,78, LightRed,$70);
Until (ext <> F1);
If (ext = F9) then With Info [currentrec] do
begin
AMORT.Amortize (Principal,Interest, Years,Year, Month - 1);
Key := #0;
end;
Until Key = Esc;
end; { PickIt }
{ ─────────────────────────────────────────────────────────────────────── }
Begin
DOScolors := TextAttr; { save the original screen color }
TextAttr := LightGray;
ClrScr;
AMORT.Init (maintitle, baseformat, 2,2, $3B,$3F,$70);
SELECTOR.Init (spectitle, specformat, 2,2, $3E,$3F,$70);
SELECTOR.Pickit;
TextAttr := DOScolors; { close the program in the original colors }
Window (1,1,80,25);
ClrScr;
End.